iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
Modern Web

前端蛇行撞牆記系列 第 28

Day28 前端蛇行撞牆記 - input 原生及 v-model 比較 / Vue 3 (下)

  • 分享至 

  • xImage
  •  

input[type=radio]

radio都是用在只能單選一項的時候,監聽 change 事件。

原生

因為 radio 只能單選一項,全部的 radio 都要綁定相同的 name,才能只選到一個,不然就會全部都能選到。

<div class="gender-content each-content">
  <label for="gender">gender: </label>
    
  <input type="radio" id="default" value="" disabled />
    
  <label for="default">choose one</label>
  <input
    name="gender"
    type="radio"
    id="male"
    value="male" />
    
  <label for="male">male</label>
  <input
    name="gender"
    type="radio"
    id="female"
    value="female" />
  <label for="female">female</label>
    
  <input
    name="gender"
    type="radio"
    id="transgender"
    value="transgender"/>
  <label for="transgender">transgender</label>
    
</div>
<p></p>
let gender = '';

const male = document.querySelector('#male')
const female = document.querySelector('#female')
const transgender = document.querySelector('#transgender')
const textP = document.querySelector('p')

male.addEventListener('change', function () {
    gerder = ''
	gender = male.value;
	textP.textContent = gender;
})

female.addEventListener('change', function () {
	gerder = ''
	gender = female.value
	textP.textContent = gender;
})

transgender.addEventListener('change', function () {
	gerder = ''
	gender = transgender.value
	textP.textContent = gender;
})

V-model

把同樣在原生裡面 name 的觀念套在 v-model 上的話就是每個 radio 的 v-model 都要是一樣的

const gender = ref('')
<div class="gender-content each-content">
  <label for="gender">gender: </label>
    
  <input type="radio" id="default" value="" disabled />
    
  <label for="default">choose one</label>
  <input
    type="radio"
    id="male"
    value="male"
    v-model="gender" />
    
  <label for="male">male</label>
  <input
    type="radio"
    id="female"
    value="female"
    v-model="gender" />
    
  <label for="female">female</label>
  <input
    type="radio"
    id="transgender"
    value="transgender"
    v-model="gender" />
  <label for="transgender">transgender</label>
    
  <p>{{ gender }}</p>
</div>

這樣就不會發生那種怎麼每個都可以選的窘境拉XD

小結

  • 原生的 radio 群組的話 name 要綁一樣的才會是單一選項。
  • vue 的 radio 則是 v-model 要綁一樣的。

select

監聽 change 事件。

<select> 比較特別,他會包著一連串的 <option>select 本身是沒有 value的,是要看現在 option 選到哪一個,那個的value 就會變成 select 的 value。

原生

<div class="flavor-content each-content">
    <label for="flavor">flavor: </label>
    
    <select name="flavor" id="flavor">       
        <option value="">--select flavor--</option>
        <option value="chocolate">chocolate</option>
        <option value="berry">berry</option>
        <option value="banana">banana</option>
        <option value="apple">apple</option>
        <option value="vanilla">vanilla</option>        
    </select>
    
</div>
<p></p>

所以就只要拿到 flavor.value 再賦值給 p 就好了

const flavor = document.querySelector('#flavor')
const text = document.querySelector('p')

flavor.addEventListener('change', function() {
	text.textContent = flavor.value;
})

我要哭了,程式碼有夠少,舒服

codepen: https://codepen.io/Jadddxx/pen/xxjQNQE?editors=1010

V-model

跟原生的一樣,所以 v-model 綁的位置是在 select 上,由他來決定 value 是什麼,而原生本來就會幫我們做到 選擇的 option 的 value 會給 select了,不必再選到 option 去拿 value。

這裡會用 v-for 來 renfer <option>

javscript:

const flavorText = ref('')

const flavorList = reactive([
  "chocolate",
  "berry",
  "banana",
  "apple",
  "vanilla",
]);

template:

<div class="flavor-content each-content">
  <label for="flavor">flavor: </label>
  <select name="flavor" id="flavor" v-model="flavorText">
    <option value="">--select flavor--</option>
    <option v-for="flavor in flavorList" :value="flavor" :key="flavor">
      {{ flavor }}
    </option>
  </select>
  <p>{{ flavorText }}</p>
</div>

小結

  • v-model 要綁在 <select>

總結

  • 留意每一個 value 跟 v-model 之間的關係。
  • 監聽input事件:
    • <input type="text"> ,<textarea> 綁定value值,響應式變數拿到的就是value的值
  • 監聽change事件:
    • <input type="checkbox">
      • 原生: 如果不設value,當checked的時候會有預設的value:true / false
      • Vue: 一樣有預設的value:true / false。要群組化的話每一個 input 都會綁相同的 v-model,而且要是個陣列,否則就會發生連動現象。
    • <input type="radio">
      • 原生: 如果有好幾個選項,每個<input name='gender'>的name要一樣的,才會是一個單一選項。
      • Vue: 其實跟原生的行為都滿像的。把原本一定要一樣的name換成v-model就好了。
    • <select>包著<option>
      • 原生: <select> 的value會隨著<option>選到的值去改變,所以原始的<select> value 就是空的,也不需要給他value。
      • vue: 由於原生的這種特性,v-model要綁在<select>上,由選到哪一個 <option> 的value來決定。

後記

原本Vue的範例已經做好了,本來只是想大概說一下原生跟Vue的差別,然後原生用簡單的範例(例如一個的checkbox)的那種,後來想說跟Vue做一樣的才能比較啊,可是用原生的去做雙向綁定好麻煩啊~~code長的跟什麼一樣....

其實都是原生的東西不懂才不知道為什麼 v-model 要放在那個位置上啊~

快結束了ya


參考資料:
MDN input
MDN <select>: The HTML Select element
Vue Form Input Bindings


上一篇
Day27 前端蛇行撞牆記 - 表單輸入 input 原生及 v-model 比較 / Vue 3 (上)
下一篇
Day29 前端蛇行撞牆記 - 可不可以給我一篇文章的時間? setTimeout() setInterval()
系列文
前端蛇行撞牆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言